package com.chatsystem.controller;

import com.chatsystem.entity.Message;
import com.chatsystem.entity.User;
import com.chatsystem.service.MessageService;
import com.chatsystem.service.UserService;
import lombok.RequiredArgsConstructor;
import org.springframework.context.event.EventListener;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.messaging.simp.SimpMessageHeaderAccessor;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.web.socket.messaging.SessionConnectedEvent;
import org.springframework.web.socket.messaging.SessionDisconnectEvent;

import java.time.LocalDateTime;
import java.util.Map;
import java.util.Optional;

/**
 * WebSocket控制器
 * 
 * @author ChatSystem
 * @version 1.0.0
 */
@Controller
@RequiredArgsConstructor
public class WebSocketController {

    private final SimpMessagingTemplate messagingTemplate;
    private final MessageService messageService;
    private final UserService userService;

    /**
     * 处理聊天消息
     * 
     * @param messageData 消息数据
     * @param headerAccessor 消息头访问器
     * @return 消息对象
     */
    @MessageMapping("/chat.sendMessage")
    @SendTo("/topic/public")
    public Message sendMessage(@Payload Map<String, Object> messageData, 
                             SimpMessageHeaderAccessor headerAccessor) {
        
        String senderUsername = (String) headerAccessor.getSessionAttributes().get("username");
        Long receiverId = Long.valueOf((String) messageData.get("receiverId"));
        String content = (String) messageData.get("content");
        String messageType = (String) messageData.get("messageType");

        // 保存消息到数据库
        var senderOpt = userService.findByUsername(senderUsername);
        if (senderOpt.isPresent()) {
            var sender = senderOpt.get();
            Message message = messageService.sendMessage(
                sender.getId(), 
                receiverId, 
                content, 
                Message.MessageType.valueOf(messageType),
                null, null, null
            );

            // 发送给特定用户
            var receiverOpt = userService.findById(receiverId);
            if (receiverOpt.isPresent()) {
                var receiver = receiverOpt.get();
                messagingTemplate.convertAndSendToUser(
                    receiver.getUsername(),
                    "/queue/messages",
                    message
                );
            }

            return message;
        }

        return null;
    }

    /**
     * 处理用户加入聊天
     * 
     * @param chatMessage 聊天消息
     * @param headerAccessor 消息头访问器
     * @return 消息对象
     */
    @MessageMapping("/chat.addUser")
    @SendTo("/topic/public")
    public Message addUser(@Payload Map<String, Object> chatMessage, 
                          SimpMessageHeaderAccessor headerAccessor) {
        
        // 添加用户名到WebSocket会话
        String username = (String) chatMessage.get("sender");
        headerAccessor.getSessionAttributes().put("username", username);
        
        // Update user status to ACTIVE and last login
        Optional<User> userOpt = userService.findByUsername(username);
        if (userOpt.isPresent()) {
            User user = userOpt.get();
            user.setOnlineStatus(User.OnlineStatus.ONLINE);
            user.setLastLoginAt(LocalDateTime.now());
            userService.updateUser(user); // Use updateUser to save the changes

            // Notify all users about the status change
            messagingTemplate.convertAndSend(
                "/topic/public/status",
                Map.of("userId", user.getId(), 
                       "type", "USER_ACTIVE", 
                       "onlineStatus", User.OnlineStatus.ONLINE.name(),
                       "lastLoginAt", user.getLastLoginAt())
            );
        }

        // 创建系统消息
        Message message = new Message();
        message.setContent(username + " 加入了聊天室");
        message.setMessageType(Message.MessageType.TEXT);
        
        return message;
    }

    /**
     * 处理消息撤回
     * 
     * @param recallData 撤回数据
     * @param headerAccessor 消息头访问器
     */
    @MessageMapping("/chat.recallMessage")
    public void recallMessage(@Payload Map<String, Object> recallData, 
                             SimpMessageHeaderAccessor headerAccessor) {
        
        String senderUsername = (String) headerAccessor.getSessionAttributes().get("username");
        Long messageId = Long.valueOf((String) recallData.get("messageId"));

        var senderOpt = userService.findByUsername(senderUsername);
        if (senderOpt.isPresent()) {
            var sender = senderOpt.get();
            
            try {
                boolean success = messageService.recallMessage(messageId, sender.getId());
                if (success) {
                    // 通知相关用户消息已撤回
                    var messageOpt = messageService.findById(messageId);
                    if (messageOpt.isPresent()) {
                        var message = messageOpt.get();
                        var receiver = message.getReceiver();
                        var senderOfOriginalMessage = message.getSender(); // 获取原始消息的发送者
                        
                        // 通知接收者消息已撤回
                        messagingTemplate.convertAndSendToUser(
                            receiver.getUsername(),
                            "/queue/messages", // 确保前端订阅的是这个队列
                            Map.of(
                                "messageId", messageId,
                                "messageType", "RECALL", // 明确消息类型为RECALL
                                "senderId", senderOfOriginalMessage.getId(), // 原始消息发送者ID
                                "senderUsername", senderOfOriginalMessage.getUsername(), // 原始消息发送者用户名
                                "senderNickname", senderOfOriginalMessage.getNickname() // 原始消息发送者昵称
                            )
                        );

                        // 同样通知发送者消息已撤回（如果不是同一个用户）
                        if (!senderOfOriginalMessage.getUsername().equals(receiver.getUsername())) {
                            messagingTemplate.convertAndSendToUser(
                                senderOfOriginalMessage.getUsername(),
                                "/queue/messages",
                                Map.of(
                                    "messageId", messageId,
                                    "messageType", "RECALL",
                                    "senderId", senderOfOriginalMessage.getId(),
                                    "senderUsername", senderOfOriginalMessage.getUsername(),
                                    "senderNickname", senderOfOriginalMessage.getNickname()
                                )
                            );
                        }

                    }
                }
            } catch (Exception e) {
                // 发送错误消息给发送者
                messagingTemplate.convertAndSendToUser(
                    senderUsername,
                    "/queue/error",
                    Map.of("error", e.getMessage())
                );
            }
        }
    }

    /**
     * 监听WebSocket连接事件
     */
    @EventListener
    public void handleWebSocketConnectListener(SessionConnectedEvent event) {
        SimpMessageHeaderAccessor headerAccessor = SimpMessageHeaderAccessor.wrap(event.getMessage());
        String username = (String) headerAccessor.getSessionAttributes().get("username");

        if (username != null) {
            Optional<User> userOpt = userService.findByUsername(username);
            if (userOpt.isPresent()) {
                User user = userOpt.get();
                user.setOnlineStatus(User.OnlineStatus.ONLINE);
                userService.updateUser(user); // Persist status change

                // Broadcast status update
                messagingTemplate.convertAndSend(
                    "/topic/public/status",
                    Map.of("userId", user.getId(), 
                           "type", "USER_ACTIVE", 
                           "onlineStatus", User.OnlineStatus.ONLINE.name(),
                           "lastLoginAt", user.getLastLoginAt())
                );
                System.out.println("User connected: " + username + ", Status: ONLINE");
            }
        }
    }

    /**
     * 监听WebSocket断开连接事件
     */
    @EventListener
    public void handleWebSocketDisconnectListener(SessionDisconnectEvent event) {
        SimpMessageHeaderAccessor headerAccessor = SimpMessageHeaderAccessor.wrap(event.getMessage());
        String username = (String) headerAccessor.getSessionAttributes().get("username");

        if (username != null) {
            Optional<User> userOpt = userService.findByUsername(username);
            if (userOpt.isPresent()) {
                User user = userOpt.get();
                user.setOnlineStatus(User.OnlineStatus.OFFLINE);
                userService.updateUser(user); // Persist status change

                // Broadcast status update
                messagingTemplate.convertAndSend(
                    "/topic/public/status",
                    Map.of("userId", user.getId(), 
                           "type", "USER_OFFLINE", 
                           "onlineStatus", User.OnlineStatus.OFFLINE.name(),
                           "lastLoginAt", user.getLastLoginAt())
                );
                System.out.println("User disconnected: " + username + ", Status: OFFLINE");
            }
        }
    }
} 